home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Crawling Systems Archive Release 1.0
/
Black Crawling Systems Archive Release 1.0 (L0pht Heavy Industries, Inc.)(1997).ISO
/
blackcrwl
/
elctrnic
/
tomlpt.txt
< prev
next >
Wrap
Text File
|
1996-08-24
|
16KB
|
306 lines
Your PC's Printer Port: a Window on the Real World
Tom Dickinson tsd@bnl.gov
The printer port or parallel port on your IBM computer is
well suited for hardware control, data input, or other
interfacing. If you just send (write or output) a number to the
correct processor I/O port the corresponding bits will appear as
ones and zeros (5 volts and 0 volts) on the connector pins on the
printer adapter. It's as simple as that. It's nearly as simple
to get signals back, but there are only five bits of input -- the
status signals that the PC expects from the printer.
The printer port works well as a hardware interface because
it is a "real-time" device. When you output a number to the
port, voltages appear on the connector pins, and when you input
you get the real time status of the bits (voltages) in the input
pins. This is in contrast to the serial port which handles
things by the RS232 protocol and sends and receives strings of
pulses which have to be 're-assembled' into meaningful numbers.
RS232 also uses 'handshaking' signals to figure out when to start
and stop strings of pulses and when to expect another batch.
When the printer adapter is feeding a printer it also uses
handshaking, hardware interrupts and so forth, but for our simple
interfacing we can ignore these.
IBM compatible computers keep in touch with the outside
world mostly through processor I/O ports. These are addressed
though the same address lines as memory, but use different
read/write lines, so they don't occupy memory address space. The
Intel processors can address 64 k I/O ports, but the IBM machines
implement only about 1000 of these, which is plenty. They are
used for keyboard, com and parallel ports, disk I/O, video, and
other things. The processor I/O ports consist of logic built
into the processor and address assignments which permit the
processor to pass data back and forth in 8 bit chunks to
different destinations and sources. They should be distinguished
from the connectors on the back of your computer for the serial
port, parallel port, etc. Each of these uses several processor
I/O ports to carry out its functions. More on this below.
Reading and writing to the I/O ports is slower than to memory,
and as computers have gotten faster and more sophisticated, some
of these functions have been changed to use Direct Memory Access
(DMA), in particular the newer video and disk interfaces.
IBM compatible computers accommodate three printer adapters,
that is, three sets of processor I/O ports are assigned to this
function. When the computer boots up, the POST program detects
any printer adapters and assigns 'logical' ports to them, LPT1,
LPT2, and LPT3. Which port addresses are assigned to LPT1, 2, or
3 depends on whether the printer adapter is part of the video
card, but for hardware interfacing we don't care, since the
logical designations are mostly used by applications programs.
Each printer adapter uses three processor I/O ports. The
first is for data output, the second for input of status signals
from the printer, and the third is for commands that go to the
printer. The three are known as the data, status, and control
ports. You can execute a 'read' to the first and third ports,
but all that you'll see is the state of the latches set by the
last 'write'. Doing a read on the second port returns the state
of the five status signals on the printer connector, while
writing to that port doesn't do anything. The physical address
of a printer adapter card is determined by how the computer
address lines are connected up to the logic on the card, and most
adapters have a jumper plug so you can select 378h or 278h. The
first (data output) port is the base address, and the status and
control ports mentioned above are base+1 and base+2. The three
base addresses available for printer adapters are 378h, 278h, and
3BCh. These are hexadecimal numbers, indicated by the 'h' after
each one.
You will need to know the physical addresses of your printer
adapter in order to send and get signals, so here's how to figure
it out. If your printer connector is on your mono or CGA video
card, then the base address is almost certainly 3BCh. That means
that the data output address is 3BCh, the status input address is
3BDh and the control port is 3BEh. (Base address, base+1, and
base+2. Get the picture?) If the printer connector is not on
the video adapter, then the address is probably 378h, and if not
that then it will be 278h. If you can't figure it out, run the
program on the next page and check for the pattern of voltages on
the printer connector. If it doesn't work, try again with a
different base address.
You can also use the same technique for finding the printer
adapter address that the computer does. During the Power On Self
Test, the computer looks for adapter cards, keyboard etc, and
stores address and other configuration information in the BIOS
Data Area of memory. The printer adapter base addresses are
stored at 40:0008h, and can be accessed by using DEBUG. The
DEBUG program is probably on your DOS disk, so change to that
disk or directory and type debug and hit enter. You will get a
minus sign (not blinking) at the left edge of the screen which is
the debug prompt. Type the following (with no spaces):
- d40:0008 and hit return. You will be rewarded with:
0040:0008 78 03 78 02 00 00 00 00 x.x.....
and several more lines of similar numbers and letters.
This is a "hex dump" of the contents of the eight memory
locations starting with 40:0008h. The first six number pairs are
the base addresses of the installed printer adapters. In the
example above, the first adapter is at 0378h, the second is at
0278h, and there is no LPT3 installed. The number pairs are
reversed because Intel stores such numbers in a 'low byte-high
byte' format. If you only have one adapter installed, this tells
you all you need to know. If you have more than one, you still
have to figure out which 25 pin printer connector is which,
either by opening up your computer and checking the address
selection jumpers on the adapter cards, or by doing the
experiment on the next page. After you write down the addresses
displayed, you can exit DEBUG by typing q.
You can buy a printer adapter card for $10 to $20 and set it
to a different address than the one already in your computer so
you can play around with hardware I/O and still have your printer
plugged in and ready to go. In fact, if your printer port is on
a multi I/O card or on your motherboard you should certainly do
this, so if you slip up and burn the port out, the damage is
limited.
Let's make something happen: If you write a number to the
base address I/O port, pin 2 on the 25 pin printer connector on
the back of your pc corresponds to bit 0 and pin 9 corresponds to
bit 7 and the ones in between are in order. So if you output
binary 10101010 (=hex AA =dec 170) on port 378h, and then take a
meter to the pins on the printer connector, you will find 5 volts
on pins 9, 7, 5, and 3, and zero on pins 8, 6,4, and 2. When I
say 5 and 0 volts, I mean whatever is an LS-TTL high and low,
which may be between 2.4 and 5.0 volts for a high and 0.8 and 0.0
volts for a low. Most printer adapters now days are made from
CMOS LSI chips, and the unloaded signals will be close to 5 and 0
volts. These outputs are latched, so you don't need a software
loop or anything, they will stay there until a new number is
output to the printer port.
In BASIC the relevant statement is OUT p,n where p is port
and n is data, ie the number you want to output. Try this
program.
10 INPUT "Enter a number 0 to 255 ", N%
20 OUT &H378, N%
(the &H tells BASIC that the number is hexadecimal,
otherwise it expects decimal numbers)
If you run this program, you should then find the pattern of
voltages on the printer connector corresponding to the bits of
the number you entered. If your printer adapter is set to 378h,
that is. If it doesn't work, try &H278 or &H3BC in line 20.
The assembly language equivalent to the BASIC OUT statement is:
MOV DX,p
MOV AL,n
OUT DX,AL
Inputing data to the PC is a little more complicated. Bits
3,4,5,6,and 7 correspond to connector pins 15, 13,12, 10, and 11
(note that they are not in order). When you input a byte from
the status port at 379h, bits 3 through 7 will be set according
to what voltage is on the connector pins listed above. I don't
know what is on bits 0, 1, and 2, but they are not determined by
connector voltages. Another complication is that the input from
pin 11 is inverted, so a ground on the pin gives a one bit and 5
volts gives a zero bit. The other inputs are the right way
round. By the way, these are printer signals Error, Select,
Paper out, Acknowledge, and Busy.
In BASIC to read a port you use the INP function. To be
useful, you need to assign the number that you read to a
variable. For example:
10 K% = INP(&H379)
20 N% = K% AND &HF8 rem F8h=binary 11111000. Strip last 3 bits
30 PRINT N%
If you run this with nothing connected to the printer
connector, you should get 120 (= 78h = 01111000 bin). This is
because an open TTL input usually reads high. Remember that the
top bit is inverted, and the last three bits are not connected
and are zero'ed out in line 20 of the program. Now ground pins
15, 13, 12, 10, and 11 one at a time to see the effect on the
number returned. Use a 2000 ohm resistor to do the grounding,
and you won't burn anything out if you stick it in the wrong
hole.
The assembly equivalent of INP is:
MOV DX,p
IN AL,DX
Where p is the input port (base+1).
The control port at base+2 (37Ah to follow the examples
above), can be used for four more output bits if you need them.
Pins 1, 14, 16, and 17 correspond to bits 0 through 3 of a byte
output to the control port and bits 0, 1, and 3 of this are
inverted. In addition, bit 4 of this control byte is not
connected to the printer connector, but if it is set, then the
next time pin 10 (the Acknowledge signal) goes from high to low,
the processor is interrupted. This will invoke the interrupt
service routine for the Centronics protocol, and who knows what
will happen if you are trying to control a robot or something at
the time.
You can also use this port for input. This is complicated,
but may be worth it if you need a full 8 bit byte of input. The
penalty comes in lines of programming needed to do it since you
first need to set the bottom three control outputs high, read
from the control and status ports, mask off the unused bits,
assemble the two sets of bits into a byte, then flip the inverted
bits. The control port can be used for input because it has open
collector output circuits, and if you set the outputs high then
an external signal can determine the voltage on pins 1, 14, 16,
and 17 on the parallel connector. Bits 0, 1, and 3 are inverted
on input as well as output.
To summarize: on the 25 pin female 'D' connector on the
printer adapter, pins 2 through 9 correspond to bits 0 through 7
of a byte output to the adapter base address. The voltages on
pins 15,13,12,10, and 11 determine bits 3 through 7 of the byte
input from base+1, and bit 7 will be inverted. Pins 1, 14, 16,
and 17 are driven by bits 0 through 3 output to the control port
at base+2, and bits 0, 1, and 3 are inverted. If the outputs on
these pins are set high by writing binary 00000100 to base+2
(remember the inverted bits) then external signals can be input
on these pins. Pull-up resistors of 4.7k are built into the
printer adapter. Pins 18 to 25 of the parallel connector are
ground. Unfortunately, 5 volts does not appear on the connector,
so if you need power for interface circuits you will need an
external supply or to get it from somewhere inside the computer.
Be careful since you can cause expensive damage by putting 5
volts in the wrong place or shorting it to ground.
So what can we do with this? The data bits can source a
couple of milliamps, so you could light (dimly) up to eight LED's
in patterns of your choice. (This is one way to burn out your
printer adapter, so be sure you use the right size resistor to
limit the current to 2.6 mA if you are going to attach LED's).
Or, with an external power supply, you could drive transistors to
operate relays to control up to eight devices. The inputs could
be used to keep track of whether five devices were on or off.
Not too exciting so far. More possibilities are opened up with
an A to D converter, so you can measure things and perhaps make
decisions based on the measurements. The ADC0831 is a nifty
eight bit A-D converter which can be operated with two output and
one input lines, leaving lots of I/O lines still available for
doing stuff. Description of this is left for another time.
How to Input 8 bits Through a Unidirectional Parallel Port
Tom Dickinson tsd@bnl.gov
The scheme I suggest for 8 bit input uses the three lowest
bits of the control port and the five high bits from the status
port. This is also described in Zhahai Stewart's "Parallel Port
FAQ" in section 16, mode 3B. We evidently thought of this
independently, but it is pretty obvious. This leaves one control
bit (bit 3) unused, and it could be used as a bidirectional
control or strobe bit as mentioned in the faq.
Here are some code examples:
8 bit output through the data port:
OUT &H378, N 'where N is the number you want to output
In assembly this is:
MOV DX,p
MOV AL,n
OUT DX,AL ' p is port and n is data
Here is an example of an 8 bit input using 3 control bits and 5
status bits. This is in basic to show the operations involved.
(I haven't tried this code, so it may have bugs)
The bits to be input are connected to the following pins:
BIT 7 6 5 4 3 2 1 0
PIN 11 10 12 13 15 16 14 1
OUT &H37A, &H04 'set output of bits 0-3 of cont. port high
LO = INP(&H37A) AND &H07 'input and mask bottom 3 bits
HI = INP(&H379) AND &HF8 'input and mask top 5 bits
BYTE = LO OR HI 'combine LO and HI into 8 bits
RITEBYTE = BYTE XOR &H83 'flip bits 0, 1, and 7
Ritebyte is the number (0 to 255) represented by the 8 bits input
on the connector.
The first line above may be a bit confusing, but remember
that bits 0, 1, and 3 are inverted, so to get 1111 on the pins,
you need to send out 0100. 04h = 00000100, so we also are
zeroing the top 4 bits. This insures that the interrupt enable
on bit four is not set, which might cause trouble. In basic this
routine is apt to be pretty slow, and if you need speed, you
should code in assembly. These are byte wide logical operations
which are very fast in machine language. You would then pass the
byte to a high level language to use as an integer variable. I
understand that C can do this kind of stuff very fast, if
optimized. I have no experience with this.
------------------------------------------------------------------
Thomas S. Dickinson Internet: tsd@bnl.gov
National Synchrotron Light Source (516) 282-7196 (work)
Brookhaven National Laboratory (516) 282-3238 (fax)
Upton, NY 11973 USA
also dickinso@ls7501.nsls.bnl.gov
and dickinso@bnlls1.nsls.bnl.gov
-----------------------------------------------------------------